package com.pjchat.pjchatclient.frame;

import java.awt.Color;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.ita.im.model.Message;
import com.ita.im.model.Unit;
import com.ita.im.model.UnitType;
import com.ita.im.model.User;
import com.pjchat.pjchatclient.handler.Handler;
import com.pjchat.pjchatclient.handlerfactory.HandlerFactory;
import com.pjchat.pjchatclient.printer.ClientFramePrinter;
import com.pjchat.pjchatclient.receiver.ClientReceiverRunnable;
import com.pjchat.pjchatclient.util.JsonUtil;

public class MyClientFrame extends JFrame {
	private static final long serialVersionUID = 1L;
	private BufferedReader br;
	private BufferedWriter bw;
	private Thread receiverRunnable;
	private User me;
	private User target;
	private List<User> userList;

	private JLabel myTarget;
	private JTextArea myStage;
	private JTextArea myStudio;
	private JLabel myLabelAll;
	private JCheckBox myToAll;
	private JButton myBtnShake;
	private JButton myBtnSend;
	private JList<String> myFriendList;
	private JScrollPane jsp1;
	private JScrollPane jsp2;
	private DefaultListModel<String> myFriendListModel;
	private JLabel myBackground;

	public MyClientFrame(BufferedReader br, BufferedWriter bw, User me)
			throws IOException {
		this.br = br;
		this.bw = bw;
		this.me = me;
		init();
		loadListener();

		receiverRunnable = new Thread(new ClientReceiverRunnable(this, br, bw));
		receiverRunnable.start();
		setVisible(true);
	}

	private void init() throws IOException {

		setSize(780, 680);
		setResizable(false);
		setTitle("PJChat-----" + me.getName());
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		setLocationRelativeTo(null);
		setLayout(null);
		setIconImage(new ImageIcon("kaixi.png").getImage());

		this.myTarget = new JLabel();
		this.myStage = new JTextArea();
		this.myStudio = new JTextArea();
		this.myLabelAll = new JLabel();
		this.myToAll = new JCheckBox();
		this.myBtnShake = new JButton();
		this.myBtnSend = new JButton();
		this.myFriendList = new JList<String>();
		this.jsp1 = new JScrollPane(myStage);
		this.jsp2 = new JScrollPane(myFriendList);
		this.myFriendListModel = new DefaultListModel<String>();
		this.myBackground = new JLabel(new ImageIcon("bg2.jpg"),
				SwingConstants.TRAILING);

		add(myTarget);
		add(myStudio);
		add(myLabelAll);
		add(myToAll);
		add(myBtnSend);
		add(myBtnShake);
		getContentPane().add(jsp1);
		getContentPane().add(jsp2);
		add(myBackground);

		myTarget.setBounds(10, 10, 150, 40);
		myTarget.setFont(new Font("font1", 2, 20));

		myStage.setFont(new Font("font1", 2, 13));
		myStage.setBackground(Color.WHITE);
		myStage.setEditable(false);

		myStudio.setBounds(10, 490, 550, 110);
		myStudio.setFont(new Font("font1", 2, 15));
		myStudio.setFocusable(true);

		myLabelAll.setBounds(250, 610, 40, 40);
		myLabelAll.setFont(new Font("font1", 2, 10));
		myLabelAll.setText("to All");

		myToAll.setBounds(230, 610, 20, 20);
		myToAll.setSelected(false);

		myBtnSend.setBounds(440, 610, 120, 40);
		myBtnSend.setText("SEND");

		myBtnShake.setBounds(310, 610, 120, 40);
		myBtnShake.setText("SHAKE");

		jsp1.setBounds(10, 60, 550, 420);
		jsp1.setFocusable(false);

		jsp2.setBounds(570, 60, 200, 500);
		myFriendList.setModel(myFriendListModel);

		myBackground.setBounds(0, 0, 780, 680);

		Unit unit = new Unit();
		unit.setType(UnitType.USER_LIST);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("user", me);
		unit.setValue(map);
		unit.setSuccess(true);
		Handler handler = HandlerFactory.produce(UnitType.USER_LIST);
		handler.doRequest(this, unit, br, bw);
	}

	public void loadListener() {
		myStage.addKeyListener(new KeyListener() {

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				if (e.getKeyCode() == 10) {
					System.out.println("ahah");
					Unit unit = new Unit();
					Map<String, Object> map = new HashMap<String, Object>();
					Message message = new Message();
					message.setFrom(me);
					if (myToAll.isSelected()) {
						message.setToAll(true);
					} else {
						if (MyClientFrame.this.target == null) {
							return;
						} else {
							message.setTo(MyClientFrame.this.target);
						}
					}
					message.setTime(new Date());
					message.setShake(true);

					unit.setType(UnitType.MESSAGE);
					map.put("message", message);
					unit.setValue(map);
					unit.setSuccess(true);

					Handler handler = HandlerFactory
							.produce(UnitType.USER_LOGIN);
					handler.doRequest(MyClientFrame.this, unit, br, bw);

					if (!message.isToAll() && !message.getTo().equals(me))
						ClientFramePrinter.getinstance().printMessage(myStage,
								message);
				}
			}

			@Override
			public void keyPressed(KeyEvent e) {
				// TODO Auto-generated method stub

			}
		});

		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				int a = JOptionPane.showConfirmDialog(null, "确定退出聊天？Y or N",
						"温馨提示", JOptionPane.YES_NO_OPTION);
				switch (a) {
				case JOptionPane.YES_OPTION:
					Unit unit = new Unit();
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("user", me);
					unit.setType(UnitType.USER_LOGOUT);
					unit.setValue(map);
					unit.setSuccess(true);
					try {
						bw.write(JsonUtil.unitToJsonObject(unit) + "\n");
						bw.flush();
						System.exit(0);
						receiverRunnable.interrupt();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					break;
				default:
					break;
				}
			}
		});

		myFriendList.addListSelectionListener(new ListSelectionListener() {

			@Override
			// when the value changed,it will enter this method twice
			public void valueChanged(ListSelectionEvent e) {
				if (myFriendList.getSelectedIndex() >= 0) {
					String targetName = myFriendListModel.get(myFriendList
							.getSelectedIndex());
					myTarget.setText(targetName);
					Iterator<User> iterator = userList.iterator();
					while (iterator.hasNext()) {
						User tmp = (User) iterator.next();
						if (tmp.getName().equals(targetName)) {
							target = tmp;
							break;
						}
					}
				}
			}
		});

		myBtnShake.addMouseListener(new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {
				Unit unit = new Unit();
				Map<String, Object> map = new HashMap<String, Object>();
				Message message = new Message();
				message.setFrom(me);
				if (myToAll.isSelected()) {
					message.setToAll(true);
					message.setTo(new User());
				} else {
					if (MyClientFrame.this.target == null) {
						JOptionPane.showMessageDialog(null,
								"You should have a target.");
						return;
					} else {
						message.setTo(MyClientFrame.this.target);
						message.setToAll(false);
					}
				}
				message.setContent("");
				message.setTime(new Date());
				message.setShake(true);

				unit.setType(UnitType.MESSAGE);
				map.put("message", message);
				unit.setValue(map);
				unit.setSuccess(true);

				Handler handler = HandlerFactory.produce(UnitType.USER_LOGIN);
				handler.doRequest(MyClientFrame.this, unit, br, bw);

				if (!message.isToAll() && !message.getTo().equals(me))
					ClientFramePrinter.getinstance().printMessage(myStage,
							message);
			}
		});

		myBtnSend.addMouseListener(new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {
				if ("".equals(myStudio.getText())) {

					return;
				}
				Unit unit = new Unit();
				Map<String, Object> map = new HashMap<String, Object>();
				Message message = new Message();
				message.setFrom(me);
				if (myToAll.isSelected()) {
					message.setToAll(true);
					message.setTo(new User());
				} else {
					if (MyClientFrame.this.target == null) {
						JOptionPane.showMessageDialog(null,
								"You should have a target.");
						return;
					} else {
						message.setTo(MyClientFrame.this.target);
						message.setToAll(false);
					}
				}
				message.setTime(new Date());
				message.setShake(false);
				message.setContent(myStudio.getText());
				myStudio.setText("");

				unit.setType(UnitType.MESSAGE);
				map.put("message", message);
				unit.setValue(map);
				unit.setSuccess(true);

				Handler handler = HandlerFactory.produce(UnitType.USER_LOGIN);
				handler.doRequest(MyClientFrame.this, unit, br, bw);

				if (!message.isToAll() && !message.getTo().equals(me))
					ClientFramePrinter.getinstance().printMessage(myStage,
							message);
			}
		});
	}

	public void shake() {
		Rectangle r = this.getBounds();
		int x = (int) r.getX(), y = (int) r.getY();
		for (int i = 0; i < 10; i++) {
			try {
				Thread.sleep(40);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (i % 2 == 0) {
				setLocation(x - 2, y - 2);
			} else {
				setLocation(x + 2, y + 2);
			}
		}
		setLocation(x, y);
	}

	public static void main(String[] args) throws IOException {
		MyClientFrame mcf = new MyClientFrame(null, null, null);
	}

	public List<User> getUserList() {
		return userList;
	}

	public void setUserList(List<User> userList) {
		this.userList = userList;
	}

	public JLabel getMyTarget() {
		return myTarget;
	}

	public void setMyTarget(JLabel myTarget) {
		this.myTarget = myTarget;
	}

	public JTextArea getMyStage() {
		return myStage;
	}

	public void setMyStage(JTextArea myStage) {
		this.myStage = myStage;
	}

	public JTextArea getMyStudio() {
		return myStudio;
	}

	public void setMyStudio(JTextArea myStudio) {
		this.myStudio = myStudio;
	}

	public JCheckBox getMyToAll() {
		return myToAll;
	}

	public void setMyToAll(JCheckBox myToAll) {
		this.myToAll = myToAll;
	}

	public JButton getMyBtnShake() {
		return myBtnShake;
	}

	public void setMyBtnShake(JButton myBtnShake) {
		this.myBtnShake = myBtnShake;
	}

	public JButton getMyBtnSend() {
		return myBtnSend;
	}

	public void setMyBtnSend(JButton myBtnSend) {
		this.myBtnSend = myBtnSend;
	}

	public JList<String> getMyFriendList() {
		return myFriendList;
	}

	public void setMyFriendList(JList<String> myFriendList) {
		this.myFriendList = myFriendList;
	}

	public DefaultListModel<String> getMyFriendListModel() {
		return myFriendListModel;
	}

	public void setMyFriendListModel(DefaultListModel<String> myFriendListModel) {
		this.myFriendListModel = myFriendListModel;
	}

	public User getTarget() {
		return target;
	}

	public void setTarget(User target) {
		this.target = target;
	}

	public User getMe() {
		return me;
	}

	public void setMe(User me) {
		this.me = me;
	}

	public JScrollPane getJsp1() {
		return jsp1;
	}

	public void setJsp1(JScrollPane jsp1) {
		this.jsp1 = jsp1;
	}

	public JScrollPane getJsp2() {
		return jsp2;
	}

	public void setJsp2(JScrollPane jsp2) {
		this.jsp2 = jsp2;
	}

}
